home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 February / EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso / enigma / earcd / emula / arosdv19.lha / AROS / exec / allocabs.c < prev    next >
C/C++ Source or Header  |  1996-10-24  |  4KB  |  169 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: allocabs.c,v 1.7 1996/10/24 15:50:43 aros Exp $
  4.     $Log: allocabs.c,v $
  5.     Revision 1.7  1996/10/24 15:50:43  aros
  6.     Use the official AROS macros over the __AROS versions.
  7.  
  8.     Revision 1.6  1996/10/19 17:07:23  aros
  9.     Include <aros/machine.h> instead of machine.h
  10.  
  11.     Revision 1.5  1996/09/13 17:51:21  digulla
  12.     Use IPTR
  13.  
  14.     Revision 1.4  1996/08/13 13:55:57  digulla
  15.     Replaced AROS_LA by AROS_LHA
  16.     Replaced some AROS_LH*I by AROS_LH*
  17.     Sorted and added includes
  18.  
  19.     Revision 1.3  1996/08/01 17:41:04  digulla
  20.     Added standard header for all files
  21.  
  22.     Desc:
  23.     Lang:
  24. */
  25. #include <exec/memory.h>
  26. #include <exec/alerts.h>
  27. #include <exec/execbase.h>
  28. #include <aros/machine.h>
  29. #include "memory.h"
  30.  
  31. /*****************************************************************************
  32.  
  33.     NAME */
  34.     #include <clib/exec_protos.h>
  35.  
  36.     AROS_LH2(APTR, AllocAbs,
  37.  
  38. /*  SYNOPSIS */
  39.     AROS_LHA(ULONG, byteSize, D0),
  40.     AROS_LHA(APTR,  location, D1),
  41.  
  42. /*  LOCATION */
  43.     struct ExecBase *, SysBase, 34, Exec)
  44.  
  45. /*  FUNCTION
  46.     Allocate some memory from the system memory pool at a given address.
  47.  
  48.     INPUTS
  49.     byteSize - Number of bytes you want to get
  50.     location - Where you want to get the memory
  51.  
  52.     RESULT
  53.     A pointer to some memory including the requested bytes or NULL if
  54.     the memory couldn't be allocated
  55.  
  56.     NOTES
  57.  
  58.     EXAMPLE
  59.  
  60.     BUGS
  61.  
  62.     SEE ALSO
  63.     FreeMem()
  64.  
  65.     INTERNALS
  66.  
  67.     HISTORY
  68.        17-10-95    created by M. Fleischer
  69.  
  70. ******************************************************************************/
  71. {
  72.     AROS_LIBFUNC_INIT
  73.     struct MemChunk *p1,*p2,*p3,*p4;
  74.     struct MemHeader *mh;
  75.  
  76.     /* Zero bytes requested? May return everything ;-). */
  77.     if(!byteSize)
  78.     return NULL;
  79.  
  80.     /* Align size to the requirements */
  81.     byteSize+=(IPTR)location&(MEMCHUNK_TOTAL-1);
  82.     byteSize=(byteSize+MEMCHUNK_TOTAL-1)&~(MEMCHUNK_TOTAL-1);
  83.  
  84.     /* Align the location as well */
  85.     location=(APTR)((IPTR)location&~(MEMCHUNK_TOTAL-1));
  86.  
  87.     /* Start and end(+1) of the block */
  88.     p3=(struct MemChunk *)location;
  89.     p4=(struct MemChunk *)((UBYTE *)p3+byteSize);
  90.  
  91.     /* Protect the memory list from access by other tasks. */
  92.     Forbid();
  93.  
  94.     /* Loop over MemHeader structures */
  95.     mh=(struct MemHeader *)SysBase->MemList.lh_Head;
  96.     while(mh->mh_Node.ln_Succ)
  97.     {
  98.     /* Test if the memory belongs to this MemHeader. */
  99.     if(mh->mh_Lower<=location&&mh->mh_Upper>location)
  100.     {
  101.         /*
  102.         The free memory list is only single linked, i.e. to remove
  103.         elements from the list I need the node's predessor. For the
  104.         first element I can use freeList->mh_First instead of a real
  105.         predessor.
  106.         */
  107.         p1=(struct MemChunk *)&mh->mh_First;
  108.         p2=p1->mc_Next;
  109.  
  110.         /* Follow the list to find a chunk with our memory. */
  111.         while(p2!=NULL)
  112.         {
  113. #if !defined(NO_CONSISTENCY_CHECKS)
  114.         /*
  115.             Do some constistency checks:
  116.             1. All MemChunks must be aligned to
  117.                MEMCHUNK_TOTAL.
  118.             2. The end (+1) of the current MemChunk
  119.                must be lower than the start of the next one.
  120.         */
  121.         if(  ((IPTR)p2|p2->mc_Bytes)&(MEMCHUNK_TOTAL-1)
  122.             ||(  (UBYTE *)p2+p2->mc_Bytes>=(UBYTE *)p2->mc_Next
  123.             &&p2->mc_Next!=NULL))
  124.             Alert(AN_MemCorrupt|AT_DeadEnd);
  125. #endif
  126.         /* Found a chunk that fits? */
  127.         if((UBYTE *)p2+p2->mc_Bytes>=(UBYTE *)p4&&p2<=p3)
  128.         {
  129.             /* Check if there's memory left at the end. */
  130.             if((UBYTE *)p2+p2->mc_Bytes!=(UBYTE *)p4)
  131.             {
  132.             /* Yes. Add it to the list */
  133.             p4->mc_Next=p2->mc_Next;
  134.             p4->mc_Bytes=(UBYTE *)p2+p2->mc_Bytes-(UBYTE *)p4;
  135.             p2->mc_Next=p4;
  136.             }
  137.  
  138.             /* Check if there's memory left at the start. */
  139.             if(p2!=p3)
  140.             /* Yes. Adjust the size */
  141.             p2->mc_Bytes=(UBYTE *)p3-(UBYTE *)p2;
  142.             else
  143.             /* No. Skip the old chunk */
  144.             p1->mc_Next=p2->mc_Next;
  145.  
  146.             /* Adjust free memory count */
  147.             mh->mh_Free-=byteSize;
  148.  
  149.             /* Return the memory */
  150.             Permit();
  151.             return p3;
  152.         }
  153.         /* goto next chunk */
  154.         p1=p2;
  155.         p2=p2->mc_Next;
  156.         }
  157.         /* The MemHeader didn't have the memory */
  158.         break;
  159.     }
  160.     /* Test next MemHeader */
  161.     mh=(struct MemHeader *)mh->mh_Node.ln_Succ;
  162.     }
  163.     /* There's nothing we could do */
  164.     Permit();
  165.     return NULL;
  166.     AROS_LIBFUNC_EXIT
  167. } /* AllocAbs */
  168.  
  169.